from test.asynchronous.time_out import Timeout
from test.asynchronous.notification_stream import NotificationStream
from exceptions import AssertionError
from threading import Condition


class NotificationTrace():
    
    def __init__(self, timeout_ms=1000):
        self.__trace_lock = Condition()
        self.__timeout_ms = timeout_ms
        self.__notification_trace = []

    def append(self, message):
        with self.trace_lock:
            self.trace.append(message)
            self.trace_lock.notifyAll()

    def contains_notification(self, criteria):
        timeout = Timeout(self.timeout_ms)
        stream = NotificationStream(self.trace, criteria)
        with self.trace_lock:
            while (not stream.has_matched()):
                if (timeout.has_timed_out()):
                    raise AssertionError("\n\nTimeout <" + str(self.timeout_ms) + "> milliseconds exceeded")
                timeout.wait_on(self.trace_lock)
    
    @property
    def trace_lock(self):
        return self.__trace_lock

    @property
    def trace(self):
        return self.__notification_trace

    @property
    def timeout_ms(self):
        return self.__timeout_ms
    
    @timeout_ms.setter
    def timeout_ms(self, value):
        self.__timeout_ms = value
    
    def reset_trace(self):
        self.__notification_trace = []
